// Header Protection
#ifndef _REGISTRATION_H_
#define _REGISTRATION_H_

// Include Files
#include "Event\Notification.h"

/////////////////////////////////////////////////////////////////////////////////////
// A registration is created whenever a listener begins listening for an event, it
//     provides the link between the event and the listener.
class ABCRegistration
{
public:     // methods

	inline ABCRegistration() { }

	inline virtual ~ABCRegistration() = 0 { }

	// The event was raised, send it to the derived class to get the listener and 
	//     handler.
	// _pArg : CEventArg * - the event argument
	virtual inline void Raise( CEventArg *_pArg ) = 0;

protected:  // child methods

	// The event was raised, create a new notification and and send it to the 
	//     listener.
	// _pListener : listener_t * - the listener for the event
	// _pArg : eventarg_t * - the event argument given when the event was raised
	// _pHandler : void (listener_t::*)(eventarg_t &) - the event handler in the 
	//     listener for the event.
	template< class listener_t, class eventarg_t >
	inline void Raise( listener_t *_pListener, 
		eventarg_t *_pArg, void (listener_t::*_pHandler)(eventarg_t &) )
	{
		_pListener->Raise( 
			new CNotification<listener_t, eventarg_t>(_pArg, _pHandler) );
	}

private:    // dummy definitions

	ABCRegistration( ABCRegistration const & );
	ABCRegistration &operator =( ABCRegistration const & );
};

/////////////////////////////////////////////////////////////////////////////////////
// A registration for a specific type of listener and event argument.
// listener_t : template - the type of the listener for the event
// eventarg_t : template - the type of the event argument
template< class listener_t, class eventarg_t >
class CRegistration : public ABCRegistration
{
public:     // methods

	// _pListener : listener_t * - the listener which is registering for the event
	// _pHandler : void (listener_t::*)(eventarg_t &) - the event handler for the 
	//     event in the listener.
	inline CRegistration( 
		listener_t *_pListener, void (listener_t::*_pHandler)(eventarg_t &) ) :
	m_pListener(_pListener), m_pHandler(_pHandler)
	{ }

	// The event was raised, raise it in the listener by calling the base class.
	// _pArg : CEventArg * - the event argument
	inline void Raise( CEventArg *_pArg )
	{
		ABCRegistration::Raise( m_pListener, (eventarg_t*)_pArg, m_pHandler );
	}

private:    // CEvent<eventarg_t> friend methods
	friend CEvent<eventarg_t>;

	inline listener_t const *GetListener() const { return m_pListener; }

	inline void( listener_t::* const GetHandler() const )(eventarg_t &)
	{ return m_pHandler; }

private:    // data
	listener_t *m_pListener;
	void (listener_t::*m_pHandler)(eventarg_t &);
};

// Header Protection
#endif // _REGISTRATION_H_
